// 节流,一段时间执行一次
export function throttle(func, wait = 500, isImmediate = false) {
  let timerId;
  let flag = true;
  if (isImmediate) {
    return function() {
      if (flag) {
        func.apply(this, arguments);
        flag = false;
        // 过段时间才可继续执行
        timerId = setTimeout(() => { flag = true }, wait); 
      }
    };
  }
  return function() {
    if (timerId) return;
    // 过段时间才可继续执行
    timerId = setTimeout(() => { 
      func.apply(this, arguments);
      clearTimeout(timerId);
      timerId = null;
    }, wait); 
  };
}
// 防抖，过一段时间才执行
export function debounce(func, wait = 500, isImmediate = false) {
  let timerId;
  let flag = true;
  if (isImmediate) {
    return function() {
      clearTimeout(timerId);
      if (flag) {
        func.apply(this, arguments);
        flag = false;
      }
      timerId = setTimeout(() => { flag = true }, wait);
    };
  }
  return function() {
    clearTimeout(timerId);
    timerId = setTimeout(() => func.apply(this, arguments), wait);
  };
}
// 插帧
export function interpolation(func) {
  requestIdleCallback(func);
}
// 请求排队
export function() {
  
}

export const jsonDeepClone = (value, callBack, space = null) => JSON.parse(JSON.stringify(value, callBack, space));

export const deepClone = (target) => {
    const map = new WeakMap()
    
    function isObject(target) {
        return (typeof target === 'object' && target ) || typeof target === 'function'
    }

    function clone(data) {
        if (!isObject(data)) {
            return data
        }
        if ([Date, RegExp].includes(data.constructor)) {
            return new data.constructor(data)
        }
        if (typeof data === 'function') {
            return new Function('return ' + data.toString())()
        }
        const exist = map.get(data)
        if (exist) {
            return exist
        }
        if (data instanceof Map) {
            const result = new Map()
            map.set(data, result)
            data.forEach((val, key) => {
                if (isObject(val)) {
                    result.set(key, clone(val))
                } else {
                    result.set(key, val)
                }
            })
            return result
        }
        if (data instanceof Set) {
            const result = new Set()
            map.set(data, result)
            data.forEach(val => {
                if (isObject(val)) {
                    result.add(clone(val))
                } else {
                    result.add(val)
                }
            })
            return result
        }
        const keys = Reflect.ownKeys(data)
        const allDesc = Object.getOwnPropertyDescriptors(data)
        const result = Object.create(Object.getPrototypeOf(data), allDesc)
        map.set(data, result)
        keys.forEach(key => {
            const val = data[key]
            if (isObject(val)) {
                result[key] = clone(val)
            } else {
                result[key] = val
            }
        })
        return result
    }

    return clone(target)
}
